#include <iostream>
#include <string>
#include <cstring>
#include <sstream>
#include <thread>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <sys/utsname.h>
#include <cstdlib>

// =================== 配置参数 ===================
const std::string MULTICAST_GROUP = "224.0.1.100"; // 组播地址
const int PORT = 17070;                            // 端口
const std::string CUSTOM_SN = "SN123456789";       // 自定义 SN
const std::string DEVICE_NAME = "MyDevice";        // 自定义设备名
const std::string NETWORK_INTERFACE = "eth2";      // 网卡接口，请根据实际修改（如：ens33）
// ===============================================

// 获取本机 IP 地址
std::string get_local_netcard_ipaddr(const char *card_name)
{
    int inet_sock;
    struct ifreq ifr;
    char ip_str[INET_ADDRSTRLEN];

    inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (inet_sock < 0)
    {
        return "";
    }

    strncpy(ifr.ifr_name, card_name, IFNAMSIZ - 1);
    ifr.ifr_name[IFNAMSIZ - 1] = '\0';

    if (ioctl(inet_sock, SIOCGIFADDR, &ifr) < 0)
    {
        close(inet_sock);
        return "";
    }
    strcpy(ip_str, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
    close(inet_sock);
    return std::string(ip_str);
}

// 获取主机名
std::string get_hostname()
{
    char hostname[256];
    if (gethostname(hostname, sizeof(hostname)) == 0)
    {
        return std::string(hostname);
    }
    return "unknown-host";
}

// 构建发现消息（JSON 格式字符串）
std::string build_discovery_message(const std::string &ip)
{
    std::ostringstream oss;
    oss << "{\"type\":\"discovery\",\"ip\":\"" << ip
        << "\",\"sn\":\"" << CUSTOM_SN
        << "\",\"name\":\"" << DEVICE_NAME
        << "\"}";
    return oss.str();
}

// 简单解析 JSON 风格字符串，提取字段（适用于简单命令）
bool parse_json_field(const std::string &json, const std::string &key, std::string &value)
{
    std::string pattern = "\"" + key + "\":\"";
    size_t start = json.find(pattern);
    if (start == std::string::npos)
        return false;
    start += pattern.length();
    size_t end = json.find("\"", start);
    if (end == std::string::npos)
        return false;
    value = json.substr(start, end - start);
    return true;
}

// 发送组播消息
void send_multicast()
{
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
    {
        std::cerr << "Failed to create socket for multicast send." << std::endl;
        return;
    }

    // === 关键：指定从哪个接口发送组播 ===
    struct in_addr local_interface;
    std::string local_ip = get_local_netcard_ipaddr(NETWORK_INTERFACE.c_str());
    if (local_ip.empty())
    {
        std::cerr << "Failed to get local IP for interface: " << NETWORK_INTERFACE << std::endl;
        close(sock);
        return;
    }
    local_interface.s_addr = inet_addr(local_ip.c_str());
    setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &local_interface, sizeof(local_interface));

    // === 增加 TTL，提高传播范围 ===
    int ttl = 4; // 原来是1，改为4测试
    setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));

    struct sockaddr_in addr;
    std::memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(MULTICAST_GROUP.c_str());
    addr.sin_port = htons(PORT);

    while (true)
    {
        std::string ip = get_local_netcard_ipaddr(NETWORK_INTERFACE.c_str());
        if (ip.empty())
        {
            std::cerr << "Cannot get IP, skipping send..." << std::endl;
            sleep(5);
            continue;
        }

        std::string msg = build_discovery_message(ip);
        ssize_t sent = sendto(sock, msg.c_str(), msg.size(), 0,
                              (struct sockaddr *)&addr, sizeof(addr));
        if (sent < 0)
        {
            std::cerr << "[ERROR] sendto failed: " << strerror(errno) << std::endl;
        }
        else
        {
            std::cout << "[SEND] " << msg << std::endl;
        }

        sleep(5);
    }

    close(sock);
}
// 接收组播并处理命令
void receive_multicast()
{
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
    {
        std::cerr << "Failed to create socket for multicast receive." << std::endl;
        return;
    }

    int reuse = 1;
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));

    struct sockaddr_in addr;
    std::memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(PORT);

    if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        std::cerr << "Bind failed." << std::endl;
        close(sock);
        return;
    }

    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_GROUP.c_str());
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
    setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

    char buffer[1024];
    struct sockaddr_in client_addr;
    socklen_t addr_len = sizeof(client_addr);

    std::cout << "Listening for multicast commands on " << MULTICAST_GROUP << ":" << PORT << std::endl;

    while (true)
    {
        int n = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,
                         (struct sockaddr *)&client_addr, &addr_len);
        if (n > 0)
        {
            buffer[n] = '\0';
            std::string msg(buffer);
            std::cout << "[RECV] " << msg << std::endl;
            std::string cmd;
            if (parse_json_field(msg, "cmd", cmd) && cmd == "set_ip")
            {
                std::string new_ip;
                std::string iface;
                if (parse_json_field(msg, "ip", new_ip))
                {
                    // 使用默认接口或从命令中提取
                    if (!parse_json_field(msg, "interface", iface))
                    {
                        iface = NETWORK_INTERFACE;
                    }

                    std::cout << "Received set_ip command: " << new_ip << " on " << iface << std::endl;

                    // 执行 IP 设置命令（需要 root 权限）
                    std::string cmd_line = "ip addr flush dev " + iface + " && ip addr add " + new_ip + "/24 dev " + iface;
                    std::cout << "Executing: " << cmd_line << std::endl;

                    int ret = system(cmd_line.c_str());
                    if (ret == 0)
                    {
                        std::cout << "✅ IP successfully changed to: " << new_ip << std::endl;
                    }
                    else
                    {
                        std::cerr << "❌ Failed to change IP!" << std::endl;
                    }
                }
            }
        }
    }

    close(sock);
}

// =============== 主函数 ===============
int main()
{
    std::cout << "Starting multicast device agent..." << std::endl;
    std::cout << "SN: " << CUSTOM_SN << std::endl;
    std::cout << "Device Name: " << DEVICE_NAME << std::endl;
    std::cout << "Network Interface: " << NETWORK_INTERFACE << std::endl;
    std::cout << "Multicast: " << MULTICAST_GROUP << ":" << PORT << std::endl;

    std::thread sender(send_multicast);
    std::thread receiver(receive_multicast);

    sender.join();
    receiver.join();

    return 0;
}